Computer languages specifically designed for querying and data retrieval within databases and information systems are known as query languages. A majority of query languages are declarative, in that they specify a goal to be achieved, but don't specify how to achieve it.
Query language processors, especially database ones, often deal with large (potentially infinite) volumes of data. Collecting all of the queried data in one step often requires a lot of memory and processor resources, and in some cases infinite, can be impossible. This is why some query processors use lazy evaluation (retrieving only one data item in a step) as a main evaluation paradigm.
Meanwhile, imperative languages like C and JAVA explicitly describe the computation as a sequence of steps called statements. Since many imperative languages use procedures or functions they are also called procedural. Because imperative languages are executed in sequence, they are also known as sequential. Imperative (procedural) sequential language programs are compiled into a sequence of atomic instructions. At each step, only one instruction is executed, but after the previous instruction execution is finished and all of the resulting data is collected and stored, the program state is permanently changed. Imperative languages are designed for data processing, but are not well-suited for querying.
Languages that combine both imperative and declarative (query) portions are known as hybrid languages. PL/SQL is one example, where declarative SQL language is embedded into an imperative procedural language. One problem with existing imperative-query languages is that persons writing the code must explicitly demarcate the boundary between the sequential and SQL portions of the source code. A compiler is not involved in locating the demarcation. This is because the imperative and query languages are separate, where each is handled by its own compiler.
Where more than one compiler is used, it is not possible to apply global optimization during the compilation process. Also, the boundary between imperative versus declarative is decided completely by the person writing the source code, regardless of where the resulting program may execute. An additional limitation occurs at run-time. An imperative processor is designed to do collect all data before executing a next step in a sequence. Accordingly, the imperative processor cannot benefit from data retrieval techniques often associated with query languages.
The approaches described in this section are approaches that could be pursued, but not necessarily approaches that have been previously conceived or pursued. Therefore, unless otherwise indicated, it should not be assumed that any of the approaches described in this section qualify as prior art merely by virtue of their inclusion in this section.